# -*- coding: utf-8 -*-

try:
    import configparser
except Exception:
    import ConfigParser as configparser

import os
import stat
import br.utils
import json
import br.vars
import br.configuration

PERMISSIONS_INI_FILEPATH = br.vars.SSR_BR_PLUGIN_PYTHON_ROOT_DIR + \
    "/br/config/permissions.ini"
FILE_GROUP_PERMISSIONS = "Permissions"
# FPK: File Permissions Key
FPK_MODE_FILE_LIST = "ModeFileList"
# FPK: Directory Permissions Key
FPK_MODE_DIRECTORY_LIST = "ModeDirectoryList"

EXCLUDE_MODE = stat.S_IWGRP | stat.S_IXGRP | stat.S_IWOTH | stat.S_IXOTH | stat.S_IXUSR

EXCLUDE_DIRECTORY_MODE = stat.S_IRWXU | stat.S_IXGRP | stat.S_IRGRP | stat.S_IROTH | stat.S_IXOTH

PERMISSIONS_ARG_MODE_PERMISSIONS_LIMIT = "mode-permissions-limit"
PERMISSIONS_ARG_MODE_DIRECTORY_PERMISSIONS_LIMIT = "directory-permissions-limit"

UMASK_LIMIT_PROFILE_PATH = '/etc/profile'
UMASK_LIMIT_BASHRC_PATH = '/etc/bashrc'

UMASK_LIMIT_CONF_KEY_UMASK = 'umask'


class PermissionSetting:
    def __init__(self):
        self.conf = configparser.ConfigParser()
        self.conf.read(PERMISSIONS_INI_FILEPATH)
        try:
            self.mode_filelist = self.conf.get(
                FILE_GROUP_PERMISSIONS, FPK_MODE_FILE_LIST).split(';')
        except Exception as e:
            self.mode_filelist = list()
            br.log.debug(str(e))

    def get(self):
        retdata = dict()

        mode_permissions_limit = True

        for mode_file in self.mode_filelist:
            if not os.access(mode_file, os.F_OK):
                continue
            mode = os.stat(mode_file).st_mode
            if (mode & EXCLUDE_MODE) != 0:
                mode_permissions_limit = False
                break
        retdata[PERMISSIONS_ARG_MODE_PERMISSIONS_LIMIT] = mode_permissions_limit

        br.log.debug(str(self.mode_filelist))

        return (True, json.dumps(retdata))

    def set(self, args_json):
        args = json.loads(args_json)

        if args[PERMISSIONS_ARG_MODE_PERMISSIONS_LIMIT]:
            for mode_file in self.mode_filelist:
                br.log.debug(str(mode_file))
                if not os.access(mode_file, os.F_OK):
                    continue
                mode = os.stat(mode_file).st_mode
                if mode != (mode & ~EXCLUDE_MODE):
                    os.chmod(mode_file, mode & ~EXCLUDE_MODE)

        return (True, '')


class DirectoryPermissionSetting:
    def __init__(self):
        self.conf = configparser.ConfigParser()
        self.conf.read(PERMISSIONS_INI_FILEPATH)
        try:
            self.mode_filelist = self.conf.get(
                FILE_GROUP_PERMISSIONS, FPK_MODE_DIRECTORY_LIST).split(';')
        except Exception as e:
            self.mode_filelist = list()
            br.log.debug(str(e))

    def get(self):
        retdata = dict()

        mode_permissions_limit = True

        for mode_file in self.mode_filelist:
            if not os.access(mode_file, os.F_OK):
                continue
            mode = os.stat(mode_file).st_mode
            if (mode & EXCLUDE_DIRECTORY_MODE) != EXCLUDE_DIRECTORY_MODE:
                mode_permissions_limit = False
                break
        retdata[PERMISSIONS_ARG_MODE_DIRECTORY_PERMISSIONS_LIMIT] = mode_permissions_limit

        br.log.debug(str(self.mode_filelist))

        return (True, json.dumps(retdata))

    def set(self, args_json):
        args = json.loads(args_json)

        if args[PERMISSIONS_ARG_MODE_DIRECTORY_PERMISSIONS_LIMIT]:
            for mode_file in self.mode_filelist:
                br.log.debug(str(mode_file))
                if not os.access(mode_file, os.F_OK):
                    continue
                mode = os.stat(mode_file).st_mode
                if mode != (mode & EXCLUDE_DIRECTORY_MODE):
                    os.chmod(mode_file, EXCLUDE_DIRECTORY_MODE)

        return (True, '')


class UmaskLimit:
    def __init__(self):
        self.conf_profile = br.configuration.KV(UMASK_LIMIT_PROFILE_PATH)
        self.conf_bashrc = br.configuration.KV(UMASK_LIMIT_BASHRC_PATH)

    def get(self):
        retdata = dict()
        key = 'enabled'
        profile_value = self.conf_profile.get_value(UMASK_LIMIT_CONF_KEY_UMASK)
        bashrc_value = self.conf_bashrc.get_value(UMASK_LIMIT_CONF_KEY_UMASK)
        retdata[key] = "" if not bashrc_value else int(bashrc_value)
        # 如果profile中有值，则以profile为准
        if profile_value:
            retdata[key] = int(profile_value)
        # 为了使022这个权限为不符合，按照现在的比对标准，22为符合，因此获取值设置为222
        if str(retdata[key]) and "22" in str(retdata[key]):
            retdata[key] = int(222)

        return (True, json.dumps(retdata))

    def set(self, args_json):
        args = json.loads(args_json)
        umask_value = args['enabled']
        if not umask_value:
            self.conf_profile.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '')
            self.conf_bashrc.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '')
            umask_value = "0"

        if int(umask_value) == 27:
            self.conf_profile.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '027')
            self.conf_bashrc.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '027')
        if int(umask_value) == 22:
            self.conf_profile.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '022')
            self.conf_bashrc.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '022')
        if int(umask_value) == 222:
            self.conf_profile.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '022')
            self.conf_bashrc.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '022')
        if int(umask_value) == 77:
            self.conf_profile.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '077')
            self.conf_bashrc.set_all_value(UMASK_LIMIT_CONF_KEY_UMASK, '077')
        
        cmd = "source" + " " + UMASK_LIMIT_BASHRC_PATH + " " + UMASK_LIMIT_PROFILE_PATH
        limit_open_command = '{0}'.format(cmd)
        br.utils.subprocess_not_output(limit_open_command)

        return (True, '')
